/*
* ============================================================================
*  Name        : example_004.cpp
*  Part of     : Finite state machine examples
*  Description : Async event handler
*  Version     : %version: %
*  
*
* ============================================================================
*/
#include "example_004.h"
#include "example_004.hxx" // State machine source code is here

/**
 * @file example_004.cpp
 *
 * @details
 * Event handler example. Event priorities
 *
 * @ingroup StateMachineExamples
 */
using namespace sea_examples;

// ----------------------------------------------------------------------------
// Simple Event handler launched in 'async' mode. 
// Output may not print all words,
// because Engine::Terminate will issue Ev_Sys_Terminate event which is
// higher priority then others, thus terminating state machine before all 
// events are processed
// ----------------------------------------------------------------------------
void sea_examples::launch_example_004( )
{
    SEA_TRACE_ENTRY( );

    {
        sea::ref< EventHandler > sm;
        sm << NEW EventHandler;

        if ( sm->create( 0, EventHandler_src ) != eOk ){ /* See Error codes */ }

        // Start will exit after the state machine launch in 'async' mode
        if ( sm->start( ) != eOk ){ /* See Error codes */ }

        // Fire Ev_Ext_say_hello in sync mode
        // The rest in async mode
        sm->push_event_sync( sm->Ev_Ext_say_hello( ) );
        sm->push_event( sm->Ev_Ext_say_sea( ) );
        sm->push_event( sm->Ev_Ext_say_world( ) );
    }

    // Terminate state machine. Ev_Sys_Terminate is issued
    // which can be processed before any of events above
    // except Ev_Ext_say_hello event which is synchronous.
    Engine::terminate( );
}

// ----------------------------------------------------------------------------
// Same as above plus multiple instances of the same state machine
// ----------------------------------------------------------------------------
void sea_examples::launch_example_0041( )
{
    SEA_TRACE_ENTRY( );

    // Create n instances of the same state machine
    int n = 10;

    vector< StateMachine* > container;
    EventHandler* sm;
    
    // Create and fill the array
    for ( int i = 0; i < n; i++ )
    {
        sm = NEW EventHandler;
        if ( sm->create( 0, EventHandler_src ) != eOk ){ /* See Error codes */ }
        container.insert( container.end( ), sm );
    }
    
    // Launch all in 'async' mode as specified in the source code
    if ( StateMachine::start( container ) != eOk ){ /* See Error codes */ }

    // Send events to all of them
    for ( int i = 0; i < n; i++ )
    {
        sm = reinterpret_cast< EventHandler* >( container[ i ] );
        sm->push_event( sm->Ev_Ext_say_hello( ) );
        sm->push_event( sm->Ev_Ext_say_sea( ) );
        sm->push_event( sm->Ev_Ext_say_world( ) );
    }

    // Dispose the references as long as no need for communicating
    // with the state machines
    for ( int i = 0; i < n; i++ )container[ i ]->release_ref( );

    // Terminate the framework, while all state machines are still running
    Engine::terminate( );
}


// ----------------------------------------------------------------------------
// Ctor. Base StateMachine class requires user class name to register in the 
// framework meta system
// ----------------------------------------------------------------------------
EventHandler::EventHandler( ) : 
    StateMachine( STATEMACHINE_NAME )
{
}

// ----------------------------------------------------------------------------
// Action function. Print 'Hello'
// ----------------------------------------------------------------------------
ACT_IMPL( EventHandler, say_hello )
{
    SEA_UNUSED_PARAM( );
    SEA_TRACE( "\n<<<< Hello >>>>\n" ); 
}

// ----------------------------------------------------------------------------
// Action function. Print 'sea'
// ----------------------------------------------------------------------------
ACT_IMPL( EventHandler, say_sea )
{
    SEA_UNUSED_PARAM( );
    SEA_TRACE( "\n<<<< SEA >>>>\n" ); 
}

// ----------------------------------------------------------------------------
// Action function. Print 'world'
// ----------------------------------------------------------------------------
ACT_IMPL( EventHandler, say_world )
{
    SEA_UNUSED_PARAM( );
    SEA_TRACE( "\n<<<< World! >>>>\n" ); 
}

